home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-02-26 | 6.3 KB | 157 lines | [TEXT/CCL2] |
- ;;;-*- Mode: Lisp; Package: CCL -*-
- ;;;-----------------------------------------------------------------------------
- ;;; A U T O S A V E
- ;;;-----------------------------------------------------------------------------
- #|
-
- Most of the original code is from a posting by:
-
- From: Bill St. Clair <bill@cambridge.apple.com>
- Subject: Re: Autosave Feature (and the lack thereof)
- Date: Wed, 26 Jun 91 17:05:09 -0400
-
- Modifications by Kemi Jona (jona@ils.nwu.edu) Feb/March 1992:
-
- - now is more like EMACS autosave
- - files autosaved with an appended ~
- - autosave files deleted when original file is saved
- - prompt when opening up a file with a newer autosave file
-
- Note: this file defines an AROUND method for FRED-WINDOW's
- INITIALIZE-INSTANCE and and AFTER method for FRED-WINDOW's WINDOW-SAVE.
- If either of these methods are already defined, you will be
- prompted before they get clobbered by this file.
-
- I like this method of autosaving because it doesn't clobber your
- original file. This allows you to revert to a saved version if you
- break something and want the old version back, but still have the
- security of having your worked saved periodically.
-
- Under normal operation, there shouldn't be any leftover autosave
- files (except if you crash, in which case you want them!). If for some reason
- there are, I've included a function to clean them out of a directory.
- The function is called AUTOSAVE-CLEAN-DIRECTORY.
-
- Please post enhancements to cambridge.apple.com, /pub/MCL2/contrib/.
- Some things that need work: erase autosave file when reverting window
- or doing a Save as.
-
- To use: save this file as autosave.lisp in the library folder and put the following
- in your init.lisp file:
-
- (load "ccl:library;autosave")
- (set-auto-save-period 5) ; or whatever you want
-
- The argument to SET-AUTO-SAVE-PERIOD is the number of minutes between autosaves.
-
- |#
-
- (in-package :ccl)
-
- (export '(set-auto-save-period autosave-clean-directory))
-
- (defvar *next-auto-save-time* nil)
- (defvar *auto-save-period* nil)
-
- (defun ticks () (#_TickCount))
-
- ; NIL will turn off autosaving
- (defun set-auto-save-period (minutes)
- (if minutes
- (progn
- (setq *auto-save-period* (round (* minutes 3600)))
- (without-interrupts
- (setq *next-auto-save-time*
- (min (or *next-auto-save-time* most-positive-fixnum) ; 8 year max
- (+ (ticks) *auto-save-period*)))))
- (setq *auto-save-period* nil
- *next-auto-save-time* nil)))
-
-
- ;;; this version does like emacs and autosaves the file under a
- ;;; different name (ie with an appended ~)
- ;;; modified by Kemi Jona, 2/2
-
- (defun do-auto-save ()
- (with-cursor *watch-cursor*
- (#_ShowCursor)
- (map-windows #'(lambda (win)
- (when (and (not (typep win 'listener))
- (slot-value win 'my-file-name)
- (window-needs-saving-p win))
- (set-mini-buffer win "Auto-saving...")
- (catch-cancel
- (buffer-write-file
- (fred-buffer win)
- (pathname (concatenate 'string
- (namestring (slot-value win 'my-file-name))
- "~"))
- :if-exists :overwrite))
- (set-mini-buffer win "Auto-saving...done")))
- :class 'fred-window)))
-
- (defun maybe-do-auto-save ()
- (let ((time *next-auto-save-time*)
- ticks)
- (when (and time (>= (setq ticks (ticks)) time))
- (setq *next-auto-save-time* (+ ticks *auto-save-period*))
- (do-auto-save)))
- ; NIL tells event-dispatch that we are'nt handling the event
- nil)
-
- (push 'maybe-do-auto-save *eventhook*)
-
- (defun autosave-clean-directory ()
- (let ((dir (pathname (directory-namestring (choose-file-dialog :button-string
- "Clean")))))
- (dolist (file (append (directory (merge-pathnames dir ".*~"))
- (directory (merge-pathnames dir "**~"))))
- (format t "Deleting ~S~%" file)
- (delete-file file)))
- (princ "All clean!")
- (values))
-
-
- ;;; make sure we're not clobbering any after methods that have already
- ;;; been defined elsewhere
- (when (or (not (find-method #'window-save '(:after) (list (find-class 'fred-window)) nil))
- (and (progn (warn "another AFTER method for WINDOW-SAVE is defined.")
- (ed-beep) (ed-beep) t)
- (y-or-n-p "Clobber existing AFTER method and install autosave~%~
- cleanup feature?")))
-
- ;;; delete the autosave file when saving the original one
- ;;; also known as autocleanup
-
- (defmethod window-save :after ((w fred-window))
- (let ((autosave-file (pathname (concatenate 'string
- (namestring (slot-value w 'my-file-name))
- "~"))))
- (if (probe-file autosave-file)
- (delete-file autosave-file)))))
-
- ;;; make sure we're not clobbering any after methods that have already
- ;;; been defined elsewhere
- (when (or (not (find-method #'initialize-instance '(:around) (list (find-class 'fred-window)) nil))
- (and (progn (warn "another AROUND method for INITIALIZE-INSTANCE for FRED-WINDOW~%~
- is defined.") (ed-beep) (ed-beep) t)
- (y-or-n-p "Clobber existing AROUND method and install check for~%~
- newer autosave file?")))
-
- ;; check for newer autosave file when opening and prompt if find one.
- (defmethod initialize-instance :around ((w fred-window) &rest initargs)
- (cond
- ;; only worry when there's a filename attached
- ((getf initargs :filename)
- (let* ((filename (getf initargs :filename))
- (autosave-file (pathname (concatenate 'string (namestring filename) "~"))))
- (if (and filename
- (probe-file autosave-file)
- (> (file-write-date autosave-file)
- (file-write-date filename))
- (y-or-n-dialog "An autosave file with a more recent write-date exists for this file. Do you wish to open that file instead?"))
- (apply #'call-next-method w (append (list :filename autosave-file) initargs))
- (call-next-method))))
- (t (call-next-method)))))
-
-